python 不常用知识点及性能优化方法 您所在的位置:网站首页 python list 字符串拼接 python 不常用知识点及性能优化方法

python 不常用知识点及性能优化方法

2023-03-04 17:48| 来源: 网络整理| 查看: 265

本文分为两个部分:python中一些比较不常见的知识点和性能优化方法,感兴趣的朋友可以选择性阅读。

1、__name__ 的用处

Python 为模块、类、函数等自动声明了一个__name__属性(变量),用于标识模块、类、函数等的名称。对于类和函数而言,__name__的值总是与类和函数的名称一致。

class A(): def __init__(self): pass @classmethod def f(cls): print('it is f') def temp(self): print('it is temp') temp.__name__ = 'xxx' setattr(cls, 'xxx', temp) A.f() A().xxx() # 实际调用 tmep 2、list、dict等可变类型作为函数默认参数def f(i, _d={}): try: print('try to get') return _d[i] except KeyError: _d[i] = '999' print(_d) f(10) f(10)

当list , dict等可变类型作为默认参数时,只会在定义函数的时候执行一次,有点像静态变量,定义一次后面一直使用。在之后使用函数的过程中,如果没有对默认参数进行赋值,那么将会一直使用这个初始的变量。

3、exec 动态执行代码exec函数可以用来动态执行 python 代码,还可以指定两个可选参数:globals 和 locals;globals是个dict对象,用来指定代码执行时可以使用的全局变量以及收集代码执行后的全局变量;当globals字典不包含__builtins__这个 key 时, python 会自动加一个指向builtins的引用。所以如果要禁止/限制代码使用内置函数的话, 需要同时指定__builtins__这个 key;locals可以是任何 mapping 对象,用来指定代码执行时的局部变量以及收集代码执行后的局部变量exec('foobar = 123') print(foobar) # exec(obj[, globals[, locals]]) age = 10 # globals 是个 dict 对象,用来指定代码执行时可以使用的全局变量以及收集代码执行后的全局变量: exec('abc = age + 1') # exec('abc = age + 1', {}) # 报错 exec('abc = age + 1', {'age': 2}) g = {'age': 2} exec('abc = age + 1', g) print(g['abc']) # out: 2 print(g['age']) # out: 3 # 当 globals 字典不包含 __builtins__ 这个 key 时, python 会自动加一个指向 builtins 的引用。所以如果要禁止/限制代码使用内置函数的话, 需要同时指定 __builtins__ 这个 key: exec('abc = int(\'10\')', {}) print(abc) # out: 11 # exec('abc = int(\'10\')', {'__builtins__': {}}) # 报错 #locals 可以是任何 mapping 对象,用来指定代码执行时的局部变量以及收集代码执行后的局部变量: exec('abc = age + 1', {}, {'age': 2}) print(abc) # out: 11 local = {} exec(''' name = 'jack' age = 13 ''', {}, local) print(local) # out: {'name': 'jack', 'age': 13}4、使用type()函数定义类# 实例方法 def __init__(self, name): # 实例属性 self.name = name # 类方法 @classmethod def study(cls): pass # 静态方法 @staticmethod def cal_student_num(): pass A = type( 'A', (object,), { 'role': 'student', '__init__': __init__, 'study': study, 'cal_student_num': cal_student_num })

使用type()函数创建class类的时候,只是将定义在class类内部的代码拿出来,放在外面,然后向type()函数传入三个参数name,bases,dict。name字符串类型,代表类名,比如例子中的"A";bases元组类型,代表基类(或父类),即需要继承的类对象;dict字典类型,将定义的类属性、类方法、实例方法等,以键值对的形式建立映射关系。

5、多种方法连接python字符串print('x' + 'y') print('a','b') print('c''d') print('%s %s'%('e', 'f')) str_list = ['g', 'h'] a = '' print(a.join(str_list))6、python类成员如何继承class C(): def __init__(self): print('CCCCCCC') class D(): def __init__(self): print('DDDDDDD') class A(): _C = C def __init__(self): pass @classmethod def f(cls): c = cls._C() class B(A): _C = D def __init__(self): A.__init__(self) # 子类调用父类方法 b = B() b.f() # out: DDDDDDD7、魔法方法__reduce__()的用处

当定义扩展类型时(也就是使用Python的C语言API实现的类型),如果你想pickle它们,你必须告诉Python如何pickle它们。 __reduce__ 被定义之后,当对象被Pickle时就会被调用。它要么返回一个代表全局名称的字符串,Pyhton会查找它并pickle,要么返回一个元组。这个元组包含2到5个元素,其中包括:一个可调用的对象,用于重建对象时调用;一个参数元素,供那个可调用对象使用;被传递给 __setstate__ 的状态(可选);一个产生被pickle的列表元素的迭代器(可选);一个产生被pickle的字典元素的迭代器(可选)

class ServerError(UserWarning): def error(self): # C语言接口,可将错误信息pickle成字符串 return self.__reduce__()[1] se = ServerError('456') x = se.error() # out: ('456',) print(x) def instance_name(name): try: if not isinstance(name, str): raise ServerError("名字必须是字符串") except ServerError as se: print(se.error()[0]) instance_name(123) # out: 名字必须是字符串8、在子类中自定义__del__方法时,需要手动调用父类的__del__方法class A: def __del__(self): print(f"call A().__del__") class B(A): def __del__(self): A.__del__(self) print(f"call B().__del__") b = B() del b9、python多线程中的事件管理器import threading from time import sleep def test(n, event): while not event.isSet(): print('Thread %s is ready' % n) sleep(1) event.wait() # 调用该方法的线程会被阻塞,如果设置了timeout参数,超时后,线程会停止阻塞继续执行 while event.isSet(): # 判断event的标志是否为True print('Thread %s is running' % n) sleep(1) def main(): event = threading.Event() for i in range(0, 2): th = threading.Thread(target=test, args=(i, event)) th.start() sleep(3) print('----- event is set -----') event.set() # 将event的标志设置为True,调用wait方法的所有线程将被唤醒 sleep(3) print('----- event is clear -----') event.clear() # 将event的标志设置为False,调用wait方法的所有线程将被阻塞 main()

输出结果:

10、什么是 CallableObjectclass CallableObject: def __call__(self, x): return x**2 obj = CallableObject() print(obj(3)) # out: 911、__slots__用法

__slots__是Python中的一个特殊类属性,它用于限制类实例可以具有的属性。

通常情况下,Python的类允许在实例中动态添加属性,这意味着可以在运行时轻松添加新的属性。但是,这样做可能会导致一些问题,例如增加了额外的内存占用,或者添加了意外的属性。在某些情况下,这可能会导致性能问题。

为了避免这些问题,可以使用__slots__属性来限制实例可以具有的属性。__slots__属性是一个字符串列表,其中包含类中允许的属性名称。如果使用了__slots__属性,则类实例只能具有列出的属性名称。

class MyClass: __slots__ = ['name', 'age'] def __init__(self, name, age): self.name = name self.age = age obj = MyClass('Alice', 30) print(obj.name) print(obj.age) obj.email = '[email protected]' # 试图添加未在 __slots__ 列表中的属性12、反射

在 Python 中,反射是指在运行时检查对象的能力,并获取、设置、删除对象属性、方法等。反射提供了一种动态操作对象的方法,它可以在不知道对象类型的情况下访问对象的属性和方法。

Python 的反射机制基于其对象模型,对象模型中的所有对象都具有一组特定的属性和方法,这些属性和方法都存储在对象的命名空间(namespace)中。命名空间是一个字典,用于存储对象的属性和方法名称及其对应的值。

在 Python 中,我们可以使用以下几个内置函数来实现反射:

hasattr(obj, name):检查对象 obj 是否有一个名为 name 的属性或方法。getattr(obj, name[, default]):获取对象 obj 的名为 name 的属性或方法。如果不存在,可以提供一个可选的默认值。setattr(obj, name, value):将对象 obj 的名为 name 的属性或方法设置为值 value。delattr(obj, name):删除对象 obj 的名为 name 的属性或方法。class MyClass: def __init__(self, x): self.x = x def my_method(self, y): return self.x + y # 创建一个 MyClass 的实例 obj = MyClass(10) # 使用反射获取对象的属性和方法 attr_name = "x" method_name = "my_method" if hasattr(obj, attr_name): attr_value = getattr(obj, attr_name) print(f"The value of attribute '{attr_name}' is: {attr_value}") if hasattr(obj, method_name): method = getattr(obj, method_name) result = method(5) print(f"The result of method '{method_name}' is: {result}")

13、id()用法

id() 函数可返回对象的内存地址

x = 42 y = 42 print(id(x)) # 输出 x 对象的唯一标识符 print(id(y)) # 输出 y 对象的唯一标识符 s = "hello" t = "hello" print(id(s)) # 输出 s 对象的唯一标识符 print(id(t)) # 输出 t 对象的唯一标识符

对于相同的整数和字符串值,id值是相同的,因为Python会自动缓存一些小整数和字符串,以便在不同的代码行中重用它们。

id()函数通常用于调试和优化代码,以确保对象在程序中的使用方式正确。例如,如果您想检查两个变量是否引用同一个对象,可以使用id()函数来比较它们的唯一标识符。

13、help() 和 getattr() 查看类成员信息14、python性能优化

说几个关键点:

使用生成器和迭代器,按需生成和处理数据,而不是一次将整个数据集加载到内存中使用Cython或Numba:Cython和Numba是Python的扩展库,它们允许Python代码以更高的速度运行。Cython将Python代码转换为C代码,而Numba通过使用JIT(即时编译)技术将Python代码转换为机器码;使用内置函数:比如map()和fileter()比for循环更快interning strings for efficiency# Create two strings string1 = 'hello world' string2 = 'hello world' # Check if the two strings are the same object print(string1 is string2) # False # Intern the strings string1 = intern(string1) string2 = intern(string2) # Check if the two strings are the same object print(string1 is string2) # True开启python解释器中的peephole optimizerx = 10 y = 5 z = x * y #bytecode LOAD_CONST 10 STORE_NAME x LOAD_CONST 5 STORE_NAME y LOAD_NAME x LOAD_NAME y BINARY_MULTIPLY STORE_NAME z #after optimized LOAD_CONST 5 STORE_FAST x LOAD_FAST x LOAD_CONST 5 BINARY_MULTIPLY STORE_FAST zuse generators and keys for sortingimport operator test = [(11,52,83),(61,20,40),(93,72,51)] print('before sorting: ', test) test.sort(key=operator.itemgetter(0)) print('after sorting: ', test) test.sort(key=operator.itemgetter(1)) print('after sorting: ', test) test.sort(key=operator.itemgetter(2)) print('after sorting: ', test)列表推导式优化循环使用set避免使用globals使用built-in操作cache a methodclass A(): def f(self): print('call f') a = A() for i in range(5): a.f() # using follow codes ff = a.f for i in range(5): ff()优化 string:比如,使用join拼接字符串、使用 RegEx(底层C语言实现)、isalpha()/isdigit()/startswith()/endwith()优化 if 语句:使用 代替 最后,使用 timeit、CpuProfiler、MemoryProfiler 等模块进行性能测试其他,与C++代码共通的方法,参考我C++专栏相关文章


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有